﻿using HK.Core.Extend;
using HK.Core.Serializable;
using HK.Core.Serializable.Data;
using HK.Core.Serializable.Protocol.Data;
using HK.Core.Utils;
using HK.Editor.Common;
using HK.Editor.Extend;
using HK.Editor.GUIEx.Drawer;
using HK.Editor.GUIEx.Protocol.Drawer;
using HK.Editor.GUIEx.Styles;
using HK.Editor.Serializable.Protocol;
using HK.Editor.Utils;
using UnityEditor;
using UnityEngine;

namespace HK.Editor.Serializable
{

    /// <summary>
    /// 序列化文件编辑器
    /// </summary>
    public abstract class SAssetEditor : EditorBase
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        protected SAssetEditor()
        {
            DefaultInspector = false;
        }
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="iDefaultInspector"></param>
        protected SAssetEditor(bool iDefaultInspector)
        {
            DefaultInspector = iDefaultInspector;
        }

        /// <summary>
        /// 是否显示默认的Inspector视图的UI
        /// <para>* 可在相关的构造函数或者Awake()中，提前设定该状态位</para>
        /// </summary>
        protected bool DefaultInspector { get; private set; } = false;

        /// <summary>
        /// 编辑器模式下的序列化文件
        /// </summary>
        public abstract bool IsEditor { get; }
        
        /// <summary>
        /// 静态文件标志位
        /// </summary>
        public abstract bool IsStatic { get; }
        
        /// <summary>
        /// 资产文件路径
        /// </summary>
        public abstract string AssetPath { get; }
        
#region SaveKey

        /// <summary>
        /// 取得存档Key
        /// </summary>
        /// <typeparam name="TAsset">资产编类型</typeparam>
        /// <returns>存档Key</returns>
        protected static string GetPlayerPrefsSaveKey<TAsset>() where TAsset : SAsset => $"_{typeof(TAsset).Name}_Editor_PlayerPrefs_";

#endregion

#region SerializedProperty

        /// <summary>
        /// Data Property有效/无效
        /// </summary>
        protected virtual bool DataPropertyValid => true;

        /// <summary>
        /// Body Property
        /// </summary>
        protected SerializedProperty BodyProperty { get; private set; } = null;

        /// <summary>
        /// Body是否含有有效的子节点
        /// </summary>
        protected virtual bool HasVisibleChildren => BodyProperty?.hasVisibleChildren ?? false;

        /// <summary>
        /// 校验码
        /// </summary>
        private SerializedProperty _checkCodeProperty = null; 
        
        /// <summary>
        /// 初始化可序列化对象
        /// </summary>
        protected override bool InitSerializedProperties()
        {
            if (!base.InitSerializedProperties())
            {
                this.Error("InitSerializedProperties():Failed!");
                return false;
            }
            
            _checkCodeProperty = FindSerializedProperty("checkCode");
            if (null == _checkCodeProperty)
            {
                this.Error("InitSerializedProperties():There is no property named checkCode!");
                return false;
            }
            
            BodyProperty = FindSerializedProperty("body");
            if (null == BodyProperty)
            {
                this.Error("InitSerializedProperties():There is no property named body!");
                return false;
            }
            
            // 生成头部Drawer
            var headerProperty = FindSerializedProperty("header");
            if (null == headerProperty)
            {
                this.Error("InitSerializedProperties():There is no property named header!");
                return false;
            }
            
            // 生成头部Drawer
            HeaderDrawer = GenerateHeaderDrawer(headerProperty, IsStatic, AssetPath);
            return null != HeaderDrawer;
        }

#endregion

#region Size&Rect 
        
        /// <summary>
        /// 单行高度
        /// </summary>
        protected static readonly float  SingleLineHeight = EditorConst.DefaultLineHeight;

        /// <summary>
        /// 余白 - 横向
        /// </summary>
        protected static readonly float HorizontalSpacing = EditorConst.HorizontalSpacing;

        /// <summary>
        /// 余白 : 纵向
        /// </summary>
        protected static readonly float VerticalSpacing = EditorConst.VerticalSpacing;
                
        /// <summary>
        /// 头部高度
        /// </summary>
        protected static readonly float  HeaderHeight = SingleLineHeight + VerticalSpacing;

        /// <summary>
        /// 按钮宽度 - 仅是Icon的按钮
        /// </summary>
        protected static readonly float BtnWidthIconOnly = EditorConst.BtnWidthIconOnly;
                
        /// <summary>
        /// 宽度 - 按钮 - 较短
        /// </summary>
        public static readonly float BtnWidthMidShort = EditorConst.BtnWidthMidShort;
        
        /// <summary>
        /// 展开/缩进箭头宽度
        /// </summary>
        public static readonly float ExpandArrowWidth = EditorConst.ExpandArrowWidth;

        /// <summary>
        /// 取得Property的高度
        /// </summary>
        /// <param name="iProperty">Property</param>
        /// <param name="iLabel">标题</param>
        /// <param name="iIncludeChild">是否包含子Property</param>
        /// <param name="iDeltaOffset">动态偏移量</param>
        /// <returns>Property的高度</returns>
        protected virtual float GetPropertyHeight(SerializedProperty iProperty, GUIContent iLabel, bool iIncludeChild = true, float iDeltaOffset = 0.0f)
        {
            return EditorGUI.GetPropertyHeight(iProperty, iLabel, iIncludeChild) + iDeltaOffset; 
        }

        /// <summary>
        /// 取得Body的高度
        /// </summary>
        /// <param name="iProperty">Body Property</param>
        /// <param name="iCaption">标题</param>
        /// <returns>Body的高度</returns>
        protected virtual float GetBodyHeight(SerializedProperty iProperty, GUIContent iCaption = null)
        {
            var caption = iCaption;
            if (null == caption)
            {
                caption = GUIContent.none;
            }
            return GetPropertyHeight(iProperty, caption) - VerticalSpacing;
        }

#endregion

#region Contents
        
        /// <summary>
        /// 选项按钮
        /// </summary>
        private GUIContent _optionsIconBtn;

        protected GUIContent OptionsIconBtn
        {
            get
            {
                if (null != _optionsIconBtn && null != _optionsIconBtn.image) return _optionsIconBtn;
                _optionsIconBtn = UtilsGUIEx.CreateGuiContentWithIcon(null, EditorConst.IconOptions);
                return _optionsIconBtn;
            }
        }

#endregion

#region Options
        
        /// <summary>
        /// 选项
        /// </summary>
        protected virtual int Options => (int)SAssetOperateOptions.Default;
        
#region GenericMenu

        /// <summary>
        /// 创建右键下拉菜单
        /// </summary>
        /// <param name="iOnMenuItemClicked">菜单Item点击回调</param>
        /// <returns>菜单</returns>
        private GenericMenu CreateDropMenu(GenericMenu.MenuFunction2 iOnMenuItemClicked)
        {
            var menu = new GenericMenu();
            
            // 导入
            // 导入 - Json/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportJson))
            {
                AddMenuItem(menu, "导入/Json/不加密", false, iOnMenuItemClicked, SAssetOperateOptions.ImportJson, true);
            }
            // 导入 - Json/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportJsonAes))
            {
                AddMenuItem(menu, "导入/Json/Aes", false, iOnMenuItemClicked, SAssetOperateOptions.ImportJsonAes);
            }
            // 导入 - Json/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportJsonDes))
            {
                AddMenuItem(menu, "导入/Json/Des", false, iOnMenuItemClicked, SAssetOperateOptions.ImportJsonDes);
            }
            
            // 导入 - Token/Hs256
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                AddMenuItem(menu, "导入/Token/Hs256", false, iOnMenuItemClicked, SAssetOperateOptions.ImportTokenHs256);
            }
            // 导入 - Token/Hs384
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                AddMenuItem(menu, "导入/Token/Hs384", false, iOnMenuItemClicked, SAssetOperateOptions.ImportTokenHs384);
            }
            // 导入 - Token/Hs512
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                AddMenuItem(menu, "导入/Token/Hs512", false, iOnMenuItemClicked, SAssetOperateOptions.ImportTokenHs512);
            }
            
            // 导入 - Binary/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportBinary))
            {
                AddMenuItem(menu, "导入/Binary/不加密", false, iOnMenuItemClicked, SAssetOperateOptions.ImportBinary);
            }
            // 导入 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportBinaryAes))
            {
                AddMenuItem(menu, "导入/Binary/Aes", false, iOnMenuItemClicked, SAssetOperateOptions.ImportBinaryAes);
            }
            // 导入 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ImportBinaryDes))
            {
                AddMenuItem(menu, "导入/Binary/Des", false, iOnMenuItemClicked, SAssetOperateOptions.ImportBinaryDes);
            }
            
            // 导出
            // 导出 - Json/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportAll))
            {
                AddMenuItem(menu, "导出/All", false, iOnMenuItemClicked, SAssetOperateOptions.ExportAll, true);
                menu.AddSeparator("导出/");
            }
            
            // 导出 - Json/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJsonAll))
            {
                AddMenuItem(menu, "导出/Json/All", false, iOnMenuItemClicked, SAssetOperateOptions.ExportJsonAll);
                menu.AddSeparator("导出/Json/");
            }
            // 导出 - Json/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJson))
            {
                AddMenuItem(menu, "导出/Json/不加密", false, iOnMenuItemClicked, SAssetOperateOptions.ExportJson);
            }
            // 导出 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJsonAes))
            {
                AddMenuItem(menu, "导出/Json/Aes", false, iOnMenuItemClicked, SAssetOperateOptions.ExportJsonAes);
            }
            // 导出 - Binary/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportJsonDes))
            {
                AddMenuItem(menu, "导出/Json/Des", false, iOnMenuItemClicked, SAssetOperateOptions.ExportJsonDes);
            }
            
            // 导出 - Token/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenAll))
            {
                AddMenuItem(menu, "导出/Token/All", false, iOnMenuItemClicked, SAssetOperateOptions.ExportTokenAll);
                menu.AddSeparator("导出/Token/");
            }
            // 导出 - Token/Hs256
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                AddMenuItem(menu, "导出/Token/Hs256", false, iOnMenuItemClicked, SAssetOperateOptions.ExportTokenHs256);
            }
            // 导出 - Token/Hs384
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                AddMenuItem(menu, "导出/Token/Hs384", false, iOnMenuItemClicked, SAssetOperateOptions.ExportTokenHs384);
            }
            // 导出 - Token/Hs512
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                AddMenuItem(menu, "导出/Token/Hs512", false, iOnMenuItemClicked, SAssetOperateOptions.ExportTokenHs512);
            }
            
            // 导出 - Binary/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinaryAll))
            {
                AddMenuItem(menu, "导出/Binary/All", false, iOnMenuItemClicked, SAssetOperateOptions.ExportBinaryAll);
                menu.AddSeparator("导出/Binary/");
            }
            // 导出 - Binary/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinary))
            {
                AddMenuItem(menu, "导出/Binary/不加密", false, iOnMenuItemClicked, SAssetOperateOptions.ExportBinary);
            }
            // 导出 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinaryAes))
            {
                AddMenuItem(menu, "导出/Binary/Aes", false, iOnMenuItemClicked, SAssetOperateOptions.ExportBinaryAes);
            }
            // 导出 - Binary/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ExportBinaryDes))
            {
                AddMenuItem(menu, "导出/Binary/Des", false, iOnMenuItemClicked, SAssetOperateOptions.ExportBinaryDes);
            }
            
            // 强制清空
            // 强制清空 - All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearAll))
            {
                AddMenuItem(menu, "强制清空/All", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearAll);
                menu.AddSeparator("强制清空/");
            }
            
            // 强制清空 - Json/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJsonAll))
            {
                AddMenuItem(menu, "强制清空/Json/All", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearJsonAll);
                menu.AddSeparator("强制清空/Json/");
            }
            // 强制清空 - Json/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJson))
            {
                AddMenuItem(menu, "强制清空/Json/不加密", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearJson);
            }
            // 强制清空 - Json/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJsonAes))
            {
                AddMenuItem(menu, "强制清空/Json/Aes", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearJsonAes);
            }
            // 强制清空 - Json/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                AddMenuItem(menu, "强制清空/Json/Des", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearJsonDes);
            }
            
            // 强制清空 - Token/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenAll))
            {
                AddMenuItem(menu, "强制清空/Token/All", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearTokenAll);
                menu.AddSeparator("强制清空/Token/");
            }
            // 强制清空 - Token/Hs256
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenHs256))
            {
                AddMenuItem(menu, "强制清空/Token/Hs256", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearTokenHs256);
            }
            // 强制清空 - Token/Hs384
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenHs384))
            {
                AddMenuItem(menu, "强制清空/Token/Hs384", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearTokenHs384);
            }
            // 强制清空 - Token/Hs512
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                AddMenuItem(menu, "强制清空/Token/Hs512", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearTokenHs512);
            }
            
            // 强制清空 - Binary/All
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinaryAll))
            {
                AddMenuItem(menu, "强制清空/Binary/All", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearBinaryAll);
                menu.AddSeparator("强制清空/Binary/");
            }
            // 强制清空 - Binary/不加密
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinary))
            {
                AddMenuItem(menu, "强制清空/Binary/不加密", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearBinary);
            }
            // 强制清空 - Binary/Aes
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinaryAes))
            {
                AddMenuItem(menu, "强制清空/Binary/Aes", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearBinaryAes);
            }
            // 强制清空 - Binary/Des
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                AddMenuItem(menu, "强制清空/Binary/Des", false, iOnMenuItemClicked, SAssetOperateOptions.ForceClearBinaryDes);
            }
            
            // 清空
            if (UtilsBytes.CheckBytes(Options, (int)SAssetOperateOptions.Clear))
            {
                AddMenuItem(menu, "清空", false, iOnMenuItemClicked, SAssetOperateOptions.Clear);
            }
            
            return menu;
        }

        /// <summary>
        /// 追加菜单Item
        /// </summary>
        /// <param name="iMenu">菜单</param>
        /// <param name="iMenuItemTxt">菜单选项文本</param>
        /// <param name="iOnOff">On/Off</param>
        /// <param name="iOnMenuItemClicked">菜单Item点击回调</param>
        /// <param name="iMenuItemOption">菜单选项</param>
        /// <param name="iAppendSeparator">是不是附加分割线</param>
        private void AddMenuItem(GenericMenu iMenu, string iMenuItemTxt, bool iOnOff, 
            GenericMenu.MenuFunction2 iOnMenuItemClicked, SAssetOperateOptions iMenuItemOption, 
            bool iAppendSeparator = false)
        {
            iMenu.AddItem(new GUIContent(iMenuItemTxt), iOnOff, iOnMenuItemClicked, iMenuItemOption);
            if (iAppendSeparator)
            {
                iMenu.AddSeparator("");
            }
        }

#endregion

#endregion

#region CheckCode

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        protected abstract string GenerateCheckCode(CheckMode iMode = CheckMode.Md5);

#endregion

#region Events

        /// <summary>
        /// 自动刷新
        /// </summary>
        protected abstract void AutoRefresh();

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="iOptions">选项</param>
        protected abstract void OnOptionMenuItemClicked(object iOptions);

#endregion

#region Draw

        public override void OnInspectorGUI()
        {
            if (DefaultInspector)
            {
                base.OnInspectorGUI();
                return;
            }
                    
            serializedObject.Update ();
            var curEvent = Event.current;

            var lastEnable = GUI.enabled;
            if (ReadOnly)
            {
                GUI.enabled = false;
            }
                    
            // 绘制选项
            DrawOptions(curEvent);
                    
            // 绘制头部
            HeaderDrawer?.Draw();
                    
            // 校验码
            DrawCheckCode(curEvent, _checkCodeProperty);
                    
            // 绘制Body
            if (HasVisibleChildren)
            {
                DrawBody(curEvent, BodyProperty);
            }
            GUI.enabled = lastEnable;
                    
            // 保存序列化值
            serializedObject.ApplyModifiedProperties();
			        
            // 保存变化后的值
            if (Dirty)
            {
                // 自动刷新
                AutoRefresh();
                Dirty = false;
            }
        }
        
#region Header

        /// <summary>
        /// 头部绘制器
        /// </summary>
        public ISAssetHeaderDrawer HeaderDrawer { get; protected set; } = null;

        /// <summary>
        /// 生成头部Drawer
        /// </summary>
        /// <param name="iSelf">自身Property</param>
        /// <param name="iStatic">静态标志位</param>
        /// <param name="iPath">路径</param>
        /// <returns>头部Drawer</returns>
        protected virtual ISAssetHeaderDrawer GenerateHeaderDrawer(SerializedProperty iSelf, bool iStatic, string iPath)
        {
            return SAssetHeaderDrawer.Create(iSelf, iStatic, iPath);
        }

#endregion

#region Options

        /// <summary>
        /// 绘制Body
        /// </summary>
        /// <param name="iEvent">Event</param>
        protected virtual Rect DrawOptions(Event iEvent)
        {
            var optionsBgRect = EditorGUILayout.GetControlRect(false, SingleLineHeight, EditorStyles.largeLabel);
                    
            // 背景
            //optionsBgRect = DrawGenericBg(optionsBgRect, iEvent);

            var optionsBtnRect = optionsBgRect;
            optionsBtnRect.xMin = optionsBtnRect.xMax - BtnWidthIconOnly;
            var rect = optionsBtnRect;
            optionsBtnRect = UtilsGUIEx.DrawButton(optionsBtnRect, iEvent, OptionsIconBtn,
                () =>
                {
                    var menu = CreateDropMenu(OnOptionMenuItemClicked);
                    menu.DropDown(rect);
                }, Color.clear, GuiExHelper.PreButton);
            return optionsBtnRect;
        }

#endregion
        
#region CheckCode

        private GUIContent refreshBtnContent = null;
        //private GUIContent refreshBtnContent = UtilsGUIEx.CreateGuiContent("刷新");
                
        /// <summary>
        /// 绘制验证码
        /// </summary>
        /// <param name="iEvent">Event</param>
        /// <param name="iProperty">Property</param>
        private void DrawCheckCode(Event iEvent, SerializedProperty iProperty)
        {
            if(null == iProperty) return;

            // 若尚无验证码，则生成
            if (string.IsNullOrEmpty(iProperty.stringValue))
            {
                iProperty.stringValue = GenerateCheckCode();
            }
            
            var bodyBgRect = EditorGUILayout.GetControlRect(false, GetBodyHeight(iProperty), EditorStyles.largeLabel);
            bodyBgRect.yMax += VerticalSpacing;
                    
            // 背景
            bodyBgRect = DrawGenericBg(bodyBgRect, iEvent);

            if (null == refreshBtnContent)
            {
                refreshBtnContent = UtilsGUIEx.CreateGuiContentWithIcon("刷新", EditorConst.IconRefresh);
            }

            var refreshBtnRect = bodyBgRect;
            refreshBtnRect.xMax -= HorizontalSpacing;
            refreshBtnRect.xMin = refreshBtnRect.xMax - BtnWidthMidShort;
            refreshBtnRect = UtilsGUIEx.DrawButton(refreshBtnRect, iEvent, refreshBtnContent,
                () =>
                {
                    iProperty.stringValue = GenerateCheckCode();
                }, ColorEx.Chartreuse0);
                    
            // 绘制
            var bodyRect = bodyBgRect;
            bodyRect.xMax = refreshBtnRect.xMin - HorizontalSpacing;
            //bodyRect.yMin += 1;
            bodyRect.yMax -= 1;
            EditorGUI.PropertyField(bodyRect, iProperty);
        }

#endregion

        /// <summary>
        /// 绘制Body
        /// </summary>
        /// <param name="iEvent">Event</param>
        /// <param name="iProperty">Property</param>
        protected virtual void DrawBody(Event iEvent, SerializedProperty iProperty)
        {
            if(null == iProperty) return;
                    
            var bodyBgRect = EditorGUILayout.GetControlRect(false, GetBodyHeight(iProperty), EditorStyles.largeLabel);
            
            // 背景
            bodyBgRect = DrawGenericBg(bodyBgRect, iEvent);
                    
            // 绘制
            var bodyRect = bodyBgRect;
            EditorGUI.PropertyField(bodyRect, iProperty);
        }

#endregion

    }

    /// <summary>
    /// 序列化文件编辑器
    /// </summary>
    /// <typeparam name="TAsset">序列化资产文件类型</typeparam>
    public abstract class SAssetEditor<TAsset> : SAssetEditor, ISAssetEditor<TAsset>
        where TAsset : SAsset
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        protected SAssetEditor() : base() {}
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="iDefaultInspector"></param>
        protected SAssetEditor(bool iDefaultInspector) : base(iDefaultInspector) {}
        
        /// <summary>
        /// 序列化文件自身
        /// </summary>
        public TAsset Self { get; private set; } = null;

        /// <summary>
        /// 编辑器模式下的序列化文件
        /// </summary>
        public override bool IsEditor
        {
            get
            {
                if (default(TAsset) == Self) return false;
                return null != Self.Header && Self.Header.Editor;
            }
        }
        
        /// <summary>
        /// 静态文件标志位
        /// </summary>
        public override bool IsStatic => default(TAsset) == Self || Self.Static;

        /// <summary>
        /// 资产文件路径
        /// </summary>
        public override string AssetPath 
        {
            get
            {
                if (default(TAsset) == Self) return null;
                return Self.Path;
            }
        }

        protected override void Awake()
        {
            base.Awake();
            
            Self = target as TAsset;
            if (null == Self)
            {
                this.Error("Awake():Failed(The type of target is not {0})!", typeof(TAsset).Name);
                return;
            }
        }

#region SerializedProperty

        /// <summary>
        /// 初始化可序列化对象
        /// </summary>
        protected override bool InitSerializedProperties()
        {
            if (default(TAsset) == Self)
            {
                this.Error("InitSerializedProperties():The self is null!");
                return false;
            }
            
            return base.InitSerializedProperties();
        }

#endregion

#region CheckCode

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        protected override string GenerateCheckCode(CheckMode iMode = CheckMode.Md5)
        {
            if(default(TAsset) == Self) return null;
            return Self.GenCheckCode(iMode);
        }

#endregion

#region Events
        
        /// <summary>
        /// 自动刷新
        /// </summary>
        protected override void AutoRefresh()
        {
            if(default(TAsset) == Self) return;
                    
            // 刷新
            Self.Refresh();
                                        
            UtilsSEAssets.SetAssetDirty (Self);
            UtilsSEAssets.AssetsRefresh();
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="iOptions">选项</param>
        protected override void OnOptionMenuItemClicked(object iOptions)
        {
            var operateOptions = (int)iOptions;
            // 清空
            if(UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.Clear))
            {
                Self.Clear((int)SAssetOperateOptions.Clear);
            }
            
            // 导入
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportJson) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportJsonAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportJsonDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportTokenHs256) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportTokenHs384) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportTokenHs512) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportBinary) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportBinaryAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ImportBinaryDes))
            {
                Self.Import(operateOptions);
            }
            
            // 导出
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportJson) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportJsonAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportJsonDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportTokenHs256) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportTokenHs384) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportTokenHs512) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportBinary) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportBinaryAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ExportBinaryDes))
            {
                Self.Export(operateOptions);
                Dirty = true;
            }
            
            // 清空
            
            if (UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.Clear) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearJson) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearJsonAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearJsonDes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearTokenHs256) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearTokenHs384) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearTokenHs512) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearBinary) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearBinaryAes) ||
                UtilsBytes.CheckBytes(operateOptions, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                Self.Clear(operateOptions);
                Dirty = true;
            }
        }

#endregion
        
    }
    
    /// <summary>
    /// 序列化文件编辑器
    /// </summary>
    /// <typeparam name="TAsset">序列化资产文件类型</typeparam>
    /// <typeparam name="TBody">Body数据类型</typeparam>
    public abstract class SAssetEditor<TAsset, TBody> : SAssetEditor<TAsset>, ISAssetEditor<TAsset, TBody>
        where TAsset : SAsset, ISAsset<TBody>
        where TBody : SAssetData, new()
    {
        
        /// <summary>
        /// 构造函数
        /// </summary>
        protected SAssetEditor() : base() {}
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="iDefaultInspector"></param>
        protected SAssetEditor(bool iDefaultInspector) : base(iDefaultInspector) {}

        /// <summary>
        /// 序列化文件数据 - Body
        /// </summary>
        public TBody Body => Self.Body;

    }
}
